#ifndef LONGKEY_BASE_OBJECT_FACTORY_H_
#define LONGKEY_BASE_OBJECT_FACTORY_H_

#include <map>

// Factory creates instances of objects based on a unique type id.
//
// AbstactProduct - base class of the product hierarchy.
// TypeId - type id for each type in the hierarchy.
// ProductCreator - callable entity to create objects.
template<class AbstractProduct,
		typename TypeId,
		typename ProductCreator = AbstractProduct* (*)()>
class Factory
{
public:
	Factory() {}

	// Registers a creator for the type id. Returns true if the creator has
	// been registered successfully.
	bool Register(const TypeId& id, ProductCreator creator)
	{
		return id_to_creators_.insert(Map::value_type(id, creator)).second;
	}

	// Unregisters a type id.
	bool Unregister(const TypeId& id)
	{
		return id_to_creators_.erase(id) == 1;
	}

	// Create an Instance of the abstract product.
	AbstractProduct* CreateObject(const TypeId& id) const
	{
		typename Map::const_iterator it = id_to_creators_.find(id);
		if (it != id_to_creators_.end())
			return (it->second)();
		else
			return NULL;
	}

private:
	typedef std::map<TypeId, ProductCreator> Map;
	Map id_to_creators_;

	DISALLOW_EVIL_CONSTRUCTORS(Factory);
};

#endif	// LONGKEY_BASE_OBJECT_FACTORY_H_